package han.chensing.latos.maker.windows.util;

import com.badlogic.gdx.scenes.scene2d.Actor;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;

import han.chensing.latos.common.level.util.ObjectUtil;

public class WidgetSetter {

    private static final Actor leftBottomActor;
    static {
        leftBottomActor=new Actor();
        leftBottomActor.setBounds(0,0,0,0);
    }
    private final List<MoveAction> moveActions=new ArrayList<>();
    private final Actor parent;

    public WidgetSetter(Actor parent) {
        this.parent = parent;
    }

    public void addAction(
            Actor major,
            Direction majorsDirection,
            Actor reference,
            Direction referencesDirection,
            float distance,
            Float width,
            Float height,
            boolean transform){
        if (ObjectUtil.checkNull(major,majorsDirection,referencesDirection))return;
        moveActions.add(new MoveAction(major, majorsDirection, reference, referencesDirection, distance, width, height,transform));
    }

    public void apply(){
        Iterator<MoveAction> iterator = moveActions.iterator();
        while(iterator.hasNext()){
            MoveAction moveAction = iterator.next();
            Actor major = moveAction.major;
            Actor reference = Optional.ofNullable(moveAction.reference).orElse(leftBottomActor);
            Direction majorsDirection = moveAction.majorsDirection;
            Direction referencesDirection = moveAction.referencesDirection;
            float distance = moveAction.distance;
            Float majorWidth = Optional.ofNullable(moveAction.width).orElse(major.getWidth());
            Float majorHeight = Optional.ofNullable(moveAction.height).orElse(major.getHeight());
            boolean transform = moveAction.transform;
            float referenceValue=switch (referencesDirection){
                case Left -> reference.getX();
                case Right -> reference.getX()+reference.getWidth();
                case Bottom -> reference.getY();
                case Top -> reference.getY()+reference.getHeight();
            };
            float newValue = referenceValue + distance;
            if (transform){
                float newX=switch (referencesDirection){
                    case Left-> reference.getX()+reference.getWidth()+distance;
                    case Right ->reference.getX()+distance;
                    default -> major.getX();
                };
                float newY=switch (referencesDirection){
                    case Top -> reference.getY()+reference.getHeight()+distance;
                    case Bottom -> reference.getY()+distance;
                    default -> major.getY();
                };
                float newWidth=switch (referencesDirection){
                    case Left,Right->major.getX()+majorWidth-newX;
                    default -> majorWidth;
                };
                float newHeight=switch (referencesDirection){
                    case Top,Bottom-> major.getY()+majorHeight-newY;
                    default -> majorHeight;
                };
                major.setBounds(newX,newY,newWidth,newHeight);
            } else {
                switch (majorsDirection) {
                    case Left -> major.setX(newValue);
                    case Right -> major.setX(newValue - major.getWidth());
                    case Bottom -> major.setY(newValue);
                    case Top -> major.setY(newValue - major.getHeight());
                }
            }
            if (!ObjectUtil.checkNull(majorWidth, majorHeight))major.setSize(majorWidth,majorHeight);
            iterator.remove();
        }
    }

    public enum Direction{
        Left,Right,Top,Bottom
    }

    public static class MoveAction{
        Direction majorsDirection;
        Direction referencesDirection;
        Actor major;
        Actor reference;
        float distance;
        Float width;
        Float height;
        boolean transform;

        public MoveAction(
                Actor major,
                Direction majorsDirection,
                Actor reference,
                Direction referencesDirection,
                float distance,
                Float width,
                Float height,
                boolean transform) {
            this.majorsDirection = majorsDirection;
            this.referencesDirection = referencesDirection;
            this.major = major;
            this.reference = reference;
            this.distance = distance;
            this.width = width;
            this.height = height;
            this.transform=transform;
        }
    }
}
